<?php

if (strpos($_SERVER['REQUEST_URI'], __FILE__) !== FALSE)
	exit;

require_once 'MSAjaxProxyGenerator.php';

class MSAjaxService
{
    # This feels like a hack... but it seems to work. :-)
    # If anyone has a better solution of how to cast to an arbitrary class, please contribute it!
    function typecast($old_object, $new_classname) {
        if (class_exists($new_classname)) {
            $old_serialized_object = serialize($old_object);
            $new_serialized_object  = 'O:' . strlen($new_classname) . ':"' . $new_classname . '":';
            $new_serialized_object .= substr($old_serialized_object, 2); # drop the "a:"
            return unserialize($new_serialized_object);
        } else {
            return false;
        }
    }

    function processRequest()
    {
        try
        {
            $path = $_SERVER['REQUEST_URI'];

            if (substr($path, strlen($path) - 3) === '/js')
            {
                $proxyGenerator = new MSAjaxProxyGenerator();
                $proxyGenerator->generateClientProxy($this);
                return;
            }

            $methodName = substr($path, strrpos($path, '/') + 1);

            $reflect = new ReflectionObject($this);
            $method = null;

            if ($reflect->hasMethod($methodName))
            {        
                $method = $reflect->getMethod($methodName);
            }

            if (is_null($method) || $method->isStatic() || !$method->isPublic() || 
                $method->getDeclaringClass()->getName() == 'MSAjaxService')
            {
                header('HTTP/1.0 500 Internal Server Error');
                throw new Exception('Method ' . $methodName . ' not found');
            }

            if ($_SERVER['REQUEST_METHOD'] !== 'POST')
            {
                header('HTTP/1.0 500 Internal Server Error');
                throw new Exception('Wrong HTTP method, should be POST');
            }

            if ((strpos($_SERVER['HTTP_CONTENT_TYPE'], 'application/json') !== 0) && (strpos($_SERVER['CONTENT_TYPE'], 'application/json') !== 0))
            {
                header('HTTP/1.0 500 Internal Server Error');
                throw new Exception('Wrong content-type, should be application/json');
            }

            $args = array();
            $postData = trim(file_get_contents('php://input'));
            if (strlen($postData) > 0)
            {
                $methodParameters = $method->getParameters();
                $argsAsParams = json_decode($postData, true);
                foreach ($methodParameters as $i => $param)
                {
                    if ($param->getClass())
                    {
                        $args[$i] = $this->typecast($argsAsParams[$param->getName()], $param->getClass()->getName());
                    }
                    else
                    {
                        $args[$i] = $argsAsParams[$param->getName()];
                    }
                }
            }

            $returnValue = $method->invokeArgs($this, $args);

            header("Content-type: application/json");
            echo json_encode($returnValue);
        }
        catch (Exception $e)
        {
            header('HTTP/1.0 500 Internal Server Error');
            header('Content-type: application/json');
            echo json_encode(array('Message' => $e->getMessage(), 'ExceptionType' => get_class($e), 'StackTrace' => $e->getTraceAsString()));
        }
    }
    
}

?>